import BaseMiddleware from './BaseMiddleware.js';
import ResponseFormatter from '../utils/ResponseFormatter.js';
import { config } from '../config.js';
import fs from 'fs';
import path from 'path';

/**
 * 错误处理中间件 - 统一处理应用程序中的错误
 */
export class ErrorHandlingMiddleware extends BaseMiddleware {
    constructor(options = {}) {
        super({
            priority: -100, // 最低优先级，最后执行
            logToFile: false,
            logDirectory: './logs',
            maxLogFileSize: 10 * 1024 * 1024, // 10MB
            includeStackTrace: config.env === 'development',
            notifyOnCritical: false,
            ...options
        });
        
        // 错误统计
        this.errorStats = {
            total: 0,
            byType: new Map(),
            byStatus: new Map(),
            byPath: new Map()
        };
        
        // 初始化日志目录
        if (this.options.logToFile) {
            this.initializeLogDirectory();
        }
    }

    /**
     * 执行错误处理逻辑
     * @param {Error} error - 错误对象
     * @param {Request} req - Express请求对象
     * @param {Response} res - Express响应对象
     * @param {Function} next - Express next函数
     */
    async execute(error, req, res, next) {
        // 如果响应已经发送，传递给默认错误处理器
        if (res.headersSent) {
            return next(error);
        }

        try {
            // 更新错误统计
            this.updateErrorStats(error, req);
            
            // 记录错误日志
            await this.logError(error, req);
            
            // 处理特定类型的错误
            const errorResponse = this.processError(error, req);
            
            // 发送错误响应
            this.sendErrorResponse(res, errorResponse);
            
            // 处理关键错误通知
            if (this.shouldNotifyOnError(error)) {
                await this.notifyOnCriticalError(error, req);
            }
        } catch (processingError) {
            console.error('[ErrorHandlingMiddleware] Error processing error:', processingError);
            
            // 发送基本错误响应
            if (!res.headersSent) {
                res.status(500).json({
                    success: false,
                    message: 'Internal Server Error',
                    timestamp: new Date().toISOString()
                });
            }
        }
    }

    /**
     * 获取错误处理中间件函数
     * @returns {Function} Express错误处理中间件函数
     */
    getMiddleware() {
        return async (error, req, res, next) => {
            await this.execute(error, req, res, next);
        };
    }

    /**
     * 处理错误，返回标准化的错误响应
     * @param {Error} error - 错误对象
     * @param {Request} req - Express请求对象
     * @returns {Object} 错误响应对象
     */
    processError(error, req) {
        const errorResponse = {
            success: false,
            message: 'Internal Server Error',
            statusCode: 500,
            timestamp: new Date().toISOString(),
            requestId: req.id || this.generateRequestId()
        };

        // 处理不同类型的错误
        switch (error.name) {
            case 'ValidationError':
                errorResponse.statusCode = 400;
                errorResponse.message = 'Validation failed';
                errorResponse.details = this.extractValidationErrors(error);
                break;

            case 'UnauthorizedError':
            case 'JsonWebTokenError':
            case 'TokenExpiredError':
                errorResponse.statusCode = 401;
                errorResponse.message = 'Unauthorized';
                break;

            case 'ForbiddenError':
                errorResponse.statusCode = 403;
                errorResponse.message = 'Forbidden';
                break;

            case 'NotFoundError':
                errorResponse.statusCode = 404;
                errorResponse.message = 'Resource not found';
                break;

            case 'ConflictError':
                errorResponse.statusCode = 409;
                errorResponse.message = 'Conflict';
                break;

            case 'TooManyRequestsError':
                errorResponse.statusCode = 429;
                errorResponse.message = 'Too many requests';
                errorResponse.retryAfter = error.retryAfter;
                break;

            case 'DatabaseError':
            case 'SequelizeError':
                errorResponse.statusCode = 500;
                errorResponse.message = 'Database error';
                if (config.env === 'development') {
                    errorResponse.details = error.message;
                }
                break;

            case 'NetworkError':
                errorResponse.statusCode = 503;
                errorResponse.message = 'Service temporarily unavailable';
                break;

            default:
                // 检查HTTP状态码
                if (error.status || error.statusCode) {
                    errorResponse.statusCode = error.status || error.statusCode;
                    errorResponse.message = error.message || this.getStatusMessage(errorResponse.statusCode);
                } else {
                    errorResponse.message = config.env === 'development' ? error.message : 'Internal Server Error';
                }
        }

        // 添加堆栈跟踪（仅开发环境）
        if (this.options.includeStackTrace && error.stack) {
            errorResponse.stack = error.stack;
        }

        // 添加错误代码
        if (error.code) {
            errorResponse.code = error.code;
        }

        return errorResponse;
    }

    /**
     * 发送错误响应
     * @param {Response} res - Express响应对象
     * @param {Object} errorResponse - 错误响应对象
     */
    sendErrorResponse(res, errorResponse) {
        // 设置响应头
        res.status(errorResponse.statusCode);
        
        // 设置安全头
        res.set({
            'X-Content-Type-Options': 'nosniff',
            'X-Frame-Options': 'DENY',
            'X-XSS-Protection': '1; mode=block'
        });

        // 发送JSON响应
        res.json(errorResponse);
    }

    /**
     * 记录错误日志
     * @param {Error} error - 错误对象
     * @param {Request} req - Express请求对象
     */
    async logError(error, req) {
        const logEntry = {
            timestamp: new Date().toISOString(),
            level: this.getErrorLevel(error),
            name: error.name || 'Error',
            message: error.message,
            stack: error.stack,
            request: {
                method: req.method,
                url: req.originalUrl,
                headers: this.sanitizeHeaders(req.headers),
                body: this.sanitizeRequestBody(req.body),
                query: req.query,
                params: req.params,
                ip: this.getClientIP(req),
                userAgent: req.get('User-Agent')
            },
            user: req.user ? {
                id: req.user.userId || req.user.id,
                roles: req.userRoles
            } : null,
            statusCode: error.status || error.statusCode || 500
        };

        // 控制台日志
        if (config.log.console) {
            console.error(`[ErrorHandlingMiddleware][${logEntry.level.toUpperCase()}]`, logEntry);
        }

        // 文件日志
        if (this.options.logToFile) {
            await this.writeLogToFile(logEntry);
        }
    }

    /**
     * 更新错误统计
     * @param {Error} error - 错误对象
     * @param {Request} req - Express请求对象
     */
    updateErrorStats(error, req) {
        this.errorStats.total++;
        
        // 按错误类型统计
        const errorType = error.name || 'Unknown';
        this.errorStats.byType.set(errorType, (this.errorStats.byType.get(errorType) || 0) + 1);
        
        // 按状态码统计
        const statusCode = error.status || error.statusCode || 500;
        this.errorStats.byStatus.set(statusCode, (this.errorStats.byStatus.get(statusCode) || 0) + 1);
        
        // 按路径统计
        const path = req.path;
        this.errorStats.byPath.set(path, (this.errorStats.byPath.get(path) || 0) + 1);
    }

    /**
     * 获取错误级别
     * @param {Error} error - 错误对象
     * @returns {string} 错误级别
     */
    getErrorLevel(error) {
        const statusCode = error.status || error.statusCode || 500;
        
        if (statusCode >= 500) {
            return 'error';
        } else if (statusCode >= 400) {
            return 'warn';
        } else {
            return 'info';
        }
    }

    /**
     * 提取验证错误详情
     * @param {Error} error - 验证错误对象
     * @returns {Array} 验证错误数组
     */
    extractValidationErrors(error) {
        if (error.errors && Array.isArray(error.errors)) {
            return error.errors;
        }
        
        if (error.details && Array.isArray(error.details)) {
            return error.details;
        }
        
        return [error.message];
    }

    /**
     * 清理请求头，移除敏感信息
     * @param {Object} headers - 请求头对象
     * @returns {Object} 清理后的请求头
     */
    sanitizeHeaders(headers) {
        const sanitized = { ...headers };
        const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token'];
        
        sensitiveHeaders.forEach(header => {
            if (sanitized[header]) {
                sanitized[header] = '[REDACTED]';
            }
        });
        
        return sanitized;
    }

    /**
     * 清理请求体，移除敏感信息
     * @param {Object} body - 请求体对象
     * @returns {Object} 清理后的请求体
     */
    sanitizeRequestBody(body) {
        if (!body || typeof body !== 'object') {
            return body;
        }
        
        const sanitized = { ...body };
        const sensitiveFields = ['password', 'token', 'secret', 'key', 'creditCard', 'ssn'];
        
        sensitiveFields.forEach(field => {
            if (sanitized[field]) {
                sanitized[field] = '[REDACTED]';
            }
        });
        
        return sanitized;
    }

    /**
     * 初始化日志目录
     */
    initializeLogDirectory() {
        try {
            if (!fs.existsSync(this.options.logDirectory)) {
                fs.mkdirSync(this.options.logDirectory, { recursive: true });
                console.log(`✓ Log directory created: ${this.options.logDirectory}`);
            }
        } catch (error) {
            console.error('[ErrorHandlingMiddleware] Failed to create log directory:', error);
            this.options.logToFile = false;
        }
    }

    /**
     * 写入日志到文件
     * @param {Object} logEntry - 日志条目
     */
    async writeLogToFile(logEntry) {
        try {
            const logFileName = `error-${new Date().toISOString().split('T')[0]}.log`;
            const logFilePath = path.join(this.options.logDirectory, logFileName);
            const logLine = JSON.stringify(logEntry) + '\n';
            
            // 检查文件大小
            if (fs.existsSync(logFilePath)) {
                const stats = fs.statSync(logFilePath);
                if (stats.size > this.options.maxLogFileSize) {
                    // 轮转日志文件
                    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
                    const rotatedFileName = `error-${new Date().toISOString().split('T')[0]}-${timestamp}.log`;
                    const rotatedFilePath = path.join(this.options.logDirectory, rotatedFileName);
                    fs.renameSync(logFilePath, rotatedFilePath);
                }
            }
            
            fs.appendFileSync(logFilePath, logLine);
        } catch (error) {
            console.error('[ErrorHandlingMiddleware] Failed to write log to file:', error);
        }
    }

    /**
     * 判断是否应该发送关键错误通知
     * @param {Error} error - 错误对象
     * @returns {boolean} 是否发送通知
     */
    shouldNotifyOnError(error) {
        if (!this.options.notifyOnCritical) {
            return false;
        }
        
        const statusCode = error.status || error.statusCode || 500;
        return statusCode >= 500 || error.name === 'DatabaseError';
    }

    /**
     * 发送关键错误通知
     * @param {Error} error - 错误对象
     * @param {Request} req - Express请求对象
     */
    async notifyOnCriticalError(error, req) {
        try {
            // 这里可以集成邮件、短信、Slack等通知服务
            console.error('[CRITICAL ERROR NOTIFICATION]', {
                error: error.message,
                stack: error.stack,
                url: req.originalUrl,
                method: req.method,
                timestamp: new Date().toISOString()
            });
        } catch (notificationError) {
            console.error('[ErrorHandlingMiddleware] Failed to send critical error notification:', notificationError);
        }
    }

    /**
     * 生成请求ID
     * @returns {string} 请求ID
     */
    generateRequestId() {
        return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }

    /**
     * 根据状态码获取默认消息
     * @param {number} statusCode - HTTP状态码
     * @returns {string} 状态消息
     */
    getStatusMessage(statusCode) {
        const statusMessages = {
            400: 'Bad Request',
            401: 'Unauthorized',
            403: 'Forbidden',
            404: 'Not Found',
            405: 'Method Not Allowed',
            409: 'Conflict',
            422: 'Unprocessable Entity',
            429: 'Too Many Requests',
            500: 'Internal Server Error',
            502: 'Bad Gateway',
            503: 'Service Unavailable',
            504: 'Gateway Timeout'
        };
        
        return statusMessages[statusCode] || 'Unknown Error';
    }

    /**
     * 获取错误统计信息
     * @returns {Object} 错误统计
     */
    getErrorStats() {
        return {
            total: this.errorStats.total,
            byType: Object.fromEntries(this.errorStats.byType),
            byStatus: Object.fromEntries(this.errorStats.byStatus),
            byPath: Object.fromEntries(this.errorStats.byPath)
        };
    }

    /**
     * 重置错误统计
     */
    resetErrorStats() {
        this.errorStats = {
            total: 0,
            byType: new Map(),
            byStatus: new Map(),
            byPath: new Map()
        };
        console.log('✓ Error statistics reset');
    }

    /**
     * 创建404处理中间件
     * @returns {Function} Express中间件函数
     */
    createNotFoundMiddleware() {
        return (req, res, next) => {
            const error = new Error(`Cannot ${req.method} ${req.originalUrl}`);
            error.name = 'NotFoundError';
            error.status = 404;
            next(error);
        };
    }
}

// 创建默认实例
export const errorHandlingMiddleware = new ErrorHandlingMiddleware();

// 导出便捷方法
export const handleErrors = () => errorHandlingMiddleware.getMiddleware();
export const handleNotFound = () => errorHandlingMiddleware.createNotFoundMiddleware();

export default ErrorHandlingMiddleware;